/************************************************************************
 * The code is owned by mainframer.cn and Shang Tao
 * Without aproval of mainframer.cn and Shang Tao, removing the copyright
 * infomation is regarded as invassion of proprietary copyright
 ***********************************************************************/
package com.mr.qa.taglib;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;

import org.apache.log4j.Logger;
import org.hibernate.Transaction;

import com.mr.qa.GlobalConfigs;
import com.mr.qa.UserSession;
import com.mr.qa.UserSessionUtil;
import com.mr.qa.bo.MrIaskCategoryStatistics;
import com.mr.qa.bo.QuestionCategory;
import com.mr.qa.dao.impl.QuestionCategoryDAO;
import com.mr.qa.util.HibernateSessionFactory;

/**
 * this class is a taglib used for creating and displaying question categories
 */

public class QuestionCategoryTaglib extends BodyTagSupport
{
    
    private static final Logger logger = Logger.getLogger(QuestionCategoryTaglib.class);
    //save the last output of left before categories are changed
    private static String outputOfLeftStructure = "";
    private static String outputOfLeftStructureLife = "";
    /**
     * L:makeLest, T:makeTop, D:makeDropdownList
     */
    private String type;
    
    /**
     * 0: iask, 1: life
     */
    private String categoryType;
    
    private Integer intCatType;
    
       
    public QuestionCategoryTaglib()
    {
        super();
    }
    
    public int doStartTag() throws JspException
    {
    
        try
        {
            JspWriter out = pageContext.getOut();
            String selectedType = this.type;
            if(selectedType.equals("L"))//left tree
            {
                out.print(makeLeft());
            }
            else if(selectedType.equals("T"))//top link
            {
                out.print(makeTop());
            }
            else if(selectedType.equals("D"))
            {
                out.print(makeDropdownList());
            }
        }
        catch (Exception e)
        { 
            throw new JspException(e);
        }
    
        return this.EVAL_PAGE;
    }
    public int doEndTag() throws JspTagException 
    {
        return 0;
    }
    
    /**
     * make left categories list
     * @return
     */
    private String makeLeft()
    {
        /*
         * 2008.12.25 16:45
         * Because the output of left category structure is identical to everyone,the building could be 
         * streamlined.
         * if categories were not updated(add,modify,delete) and output exists,return the output directly
           to improve performance.
        */
        if(!GlobalConfigs.CATEGORYCHANGED && this.outputOfLeftStructure.length() > 0 && this.intCatType == 0)
        {
            //logger.info("Categoies not changed and output built, use the previous one to improve performance.");
            return this.outputOfLeftStructure;
        }else if(!GlobalConfigs.CATEGORYCHANGED && this.outputOfLeftStructureLife.length() > 0 && this.intCatType == 1)
        {
            //logger.info("Categoies not changed and output built, use the previous one to improve performance.");
            return this.outputOfLeftStructureLife;
        }
        try
        {
            HttpServletRequest request = (HttpServletRequest)this.pageContext.getRequest();
            QuestionCategoryDAO categoryDAO = new QuestionCategoryDAO();
            QuestionCategory qc = null;
            Transaction tx = null;
            List list = null;
            try
            {
                tx = HibernateSessionFactory.getSession().beginTransaction();
                list = categoryDAO.findByType(intCatType);//level 1
                tx.commit();
            }
            catch(Exception e)
            {
                logger.error(e);    
            }
            finally
            {
                HibernateSessionFactory.closeSession();
            }
            if(list == null)return "";
            StringBuffer bf = new StringBuffer();
            String questionCategoryIdAndNamePairs = "";
            String questionCategoryIds = "";
            if(list.size() >0)
            {
                for(int i=0;i<list.size();i++)
                {
                    qc = (QuestionCategory)list.get(i);
                    if(!"N".equals(qc.getOnlyForAdmin()))
                    {
                        continue;
                    }
                    if("1".equals(qc.getState()))
                    {
                        continue;
                    }
                    questionCategoryIdAndNamePairs += qc.getId()+":"+qc.getName()+"<br>";
                    questionCategoryIds += qc.getId()+",";
                    bf.append("<a href='");
                    bf.append(request.getContextPath());
                    if(qc.getType()==0){
                    	bf.append("/question.mrqa?action=list&catId=");
                    }else if(qc.getType() == 1){
                    	bf.append("/life.mrqa?action=list&catId=");
                    }else if(qc.getType() == 2){
                    	bf.append("/tech.mrqa?action=list&catId=");
                    }
                    bf.append(qc.getId());
                    bf.append("'>");
                    bf.append(qc.getName());
                    bf.append("</a><br>");
                    Set level1Cats = qc.getMrIaskCategories();//level 2
                    if(level1Cats.size() >0)
                    {
                        Iterator level1Ite = level1Cats.iterator();
                        while(level1Ite.hasNext())
                        {
                            qc = (QuestionCategory)level1Ite.next();
                            if("0".equals(qc.getState())){
                            	questionCategoryIdAndNamePairs += "---"+qc.getId()+":"+qc.getName()+"<br>";
                            	questionCategoryIds += qc.getId()+",";
                            	bf.append("&nbsp;&nbsp;<img src='qa/images/arrow.gif' width='15' heigh='10'/><a href='");
                            	bf.append(request.getContextPath());
                            	if(qc.getType() == 0){
                            		bf.append("/question.mrqa?action=list&catId=");
	                            }else if(qc.getType() == 1){
	                            	bf.append("/life.mrqa?action=list&catId=");
	                            }else if(qc.getType() == 2){
	                            	bf.append("/tech.mrqa?action=list&catId=");
	                            }
	                            bf.append(qc.getId());
	                            bf.append("'>");
	                            bf.append(qc.getName());
	                            bf.append("</a><br>");
                            }
                        }
                    }
                    bf.append("<hr>");
                }
            }
            GlobalConfigs.QUESTION_CATEGORY_ID_NAME_PAIRS = questionCategoryIdAndNamePairs;
            GlobalConfigs.QUESTION_CATEGORY_IDS = questionCategoryIds;
            if(intCatType == 0){
            	this.outputOfLeftStructure = bf.toString();
            }else if(intCatType == 1){
            	this.outputOfLeftStructureLife = bf.toString();
            }
            return bf.toString();
            
        }
        catch(Exception e)
        {
            logger.warn(e);
        }
        return "";
        
    }
    /**
     * make the category XML output for adding and changing question cateogy pages
     * @return
     */
    private String makeDropdownList()
    {
        HttpServletRequest request = (HttpServletRequest)this.pageContext.getRequest();
        try
        {
            UserSession us = UserSessionUtil.getUserSession(request);
            boolean userHasAdminRight = false;
            boolean userHasSuperRight = false;
            if(us != null)
            {
                if("1".equals(us.getType()))
                {
                    userHasAdminRight = true;
                    userHasSuperRight = true;
                }
                else if(us.getIsSuper())
                {
                    userHasSuperRight = true;
                }
            }
            //logger.info("userHasAdminRight="+userHasAdminRight+",userHasSuperRight="+userHasSuperRight);
            QuestionCategoryDAO categoryDAO = new QuestionCategoryDAO();
            Transaction tx = null;
            List list = null;
            try
            {
                tx = HibernateSessionFactory.getSession().beginTransaction();
                list = categoryDAO.findByType(intCatType);//level 1
                tx.commit();
            }
            catch(Exception e)
            {
                logger.error(e);    
            }
            finally
            {
                HibernateSessionFactory.closeSession();
            }
            if(list == null)return "";
            StringBuffer sb = new StringBuffer();
            if(list.size() >0)//level 1
            {
                int level = 1;
                QuestionCategory qc = null;
                String catOnlyForAdmin = "";
                for(int i=0;i<list.size();i++)
                {
                    qc = (QuestionCategory)list.get(i);
                    catOnlyForAdmin = qc.getOnlyForAdmin();
                    //admin category, poll category, hide category not open for common users
                    if("I".equals(catOnlyForAdmin))//internal category
                    {
                        if(!userHasSuperRight)
                        {
                            continue;
                        }
                    }
                    else if("1".equals(qc.getState()))//notice category
                    {
//                        if(!userHasAdminRight)
//                        {
                            continue;
//                        }
                    }
                    else if("Y".equals(catOnlyForAdmin))
                    {
                        if(!userHasSuperRight)
                        {
                            continue;
                        }
                    }
                    else if("T".equals(catOnlyForAdmin))
                    {
                        if(!userHasSuperRight)
                        {
                            continue;
                        }
                    }
                    else if("N".equals(catOnlyForAdmin) && qc.getIsAds())//common question category being ad category
                    {
                        if(!userHasSuperRight)continue;//does not display the level 1 category 2008-8-27
                    }
                    else if("N".equals(catOnlyForAdmin) && qc.getIsTraining())//common question category being ad category
                    {
                        if(!userHasSuperRight)continue;//does not display the level 1 category 2008-8-27
                    }
                    sb.append("<cat level=\"");
                    sb.append(level);
                    sb.append("\" id=\"");
                    sb.append(qc.getId());
                    sb.append("\" name=\"");
                    String name = qc.getName();
                    if(name.indexOf("&") >= 0)
                    {
                        name = name.replaceAll("&","&amp;");
                    }
                    sb.append(name);
                    sb.append("\" type=\"");
                    sb.append(qc.getType());
                    if(qc.getMrIaskCategories().size() > 0)
                    {
                        sb.append("\">\n");                    
                        makeNextLevel(sb,level+1,qc,us);
                    }
                    else
                    {
                        sb.append("\">");
                    }
                    sb.append("</cat>\n");
                }
            }
            return sb.toString();
        }
        catch(Exception e)
        {
            logger.warn(e);
        }
        return "";
    }    
    
    private void makeNextLevel(StringBuffer sb, int level,QuestionCategory parent,UserSession us)
    {
        Set children = parent.getMrIaskCategories();
        if(children.size() >0)
        {
            String indentStr = makeIndentStr(level);
            QuestionCategory qc = null;
            Iterator ite = children.iterator();
            while(ite.hasNext())
            {
                qc = (QuestionCategory)ite.next();
                //if category is a ad one, check the super user permissions 2008-8-27
                if(qc.getIsAds())
                {
                    if(us == null)continue;
                    /*
                    else if(us.getIsSuper())
                    {
                        if(!ifSuperUserHasPermissionOnCategory(qc.getId(),us.getPermissions()))continue;    
                    }*/
                }
                sb.append(indentStr);
                sb.append("<cat level=\"");
                sb.append(level);
                sb.append("\" id=\"");
                sb.append(qc.getId());
                sb.append("\" name=\"");
                String name = qc.getName();
                if(name.indexOf("&") >= 0)
                {
                    name = name.replaceAll("&","&amp;");
                }
                sb.append(name);
                sb.append("\" type=\"");
                sb.append(qc.getType());
                if(qc.getMrIaskCategories().size() > 0)
                {
                    sb.append("\">\n");                    
                    makeNextLevel(sb,level+1,qc,us);
                }
                else
                {
                    sb.append("\">");
                }
                if(qc.getMrIaskCategories().size() > 0)
                {
                    sb.append(indentStr);
                }    
                sb.append("</cat>\n");
                
            }
        }
    }
    
    private String makeIndentStr(int level)
    {
        String indentStr = "";
        for(int i=0;i<level;i++)indentStr = indentStr+"   ";
        return indentStr;
    }
    
    //check if a super user has permission on one ad category
    private boolean ifSuperUserHasPermissionOnCategory(int catId,String userPermissions)
    {
        if(userPermissions == null || userPermissions.trim().length() == 0)return false;
        return (userPermissions.indexOf(catId+",") > 0)?true:false;
    }
    
    
    /**
     * make list for a specified category
     * @return
     */
    private String makeTop1()
    {
        try
        {
            HttpServletRequest request = (HttpServletRequest)this.pageContext.getRequest();
            QuestionCategoryDAO categoryDAO = new QuestionCategoryDAO();
            QuestionCategory qc = null;
            String catId = request.getParameter("catId");
            if(catId == null)return "";
            Transaction tx = null;
            QuestionCategory parent = null;
            try
            {
                tx = HibernateSessionFactory.getSession().beginTransaction();
                parent = categoryDAO.findById(new Integer(catId));                
                tx.commit();
            }
            catch(Exception e)
            {
                logger.error(e);    
            }
            finally
            {
                HibernateSessionFactory.closeSession();
            }
            if(parent != null)
            {
                StringBuffer bf = new StringBuffer();
                Set level2Cats = parent.getMrIaskCategories();//level 2
                if(level2Cats.size() > 0)
                {
                    Iterator level2Ite = level2Cats.iterator();
                    int i = 0;
                     MrIaskCategoryStatistics mics = null;
                    while(level2Ite.hasNext())
                    {
                        qc = (QuestionCategory)level2Ite.next();
                        bf.append("<li><a href='");
                        bf.append(request.getContextPath());
                        if(qc.getType() == 0){
                        	bf.append("/question.mrqa?action=list&catId=");
                        }else if(qc.getType() == 1){
                        	bf.append("/life.mrqa?action=list&catId=");
                        }else if(qc.getType() == 2){
                        	bf.append("/tech.mrqa?action=list&catId=");
                        }
                        bf.append(qc.getId());
                        bf.append("'>");
                        bf.append(qc.getName());
                        bf.append("(");
                        mics = qc.getMrIaskCategoryStatistics();
                        if(mics == null)
                        {
                            bf.append("0");
                        }
                        else
                        {
                            bf.append(""+mics.getTotal());
                        }
                        bf.append(")");
                        bf.append("</a>");
                        i = i+1;
                        if(i == 2)
                        {
                            i = 0;
                        }
                    }
                }
                if(bf.toString().length() >0)
                    return "<ul id=\"questioncategoryontop\">\n"+bf.toString()+"</ul>\n";
            }    
        }
        catch(Exception e)
        {
            logger.warn(e);
        }
        return "";
    }
    
    private String makeTop()
    {
        try
        {
            HttpServletRequest request = (HttpServletRequest)this.pageContext.getRequest();
            String catId = request.getParameter("catId");
            Transaction tx = null;
            try
            {
                tx = HibernateSessionFactory.getSession().beginTransaction();
                QuestionCategoryDAO categoryDAO = new QuestionCategoryDAO();
                Collection categories = null;
                if(catId == null)
                {
                    categories = categoryDAO.findByType(intCatType);
                }
                else
                {
                    QuestionCategory parent = null;                
                    parent = categoryDAO.findById(new Integer(catId));
                    categories = parent.getMrIaskCategories();
                }
                tx.commit();
                if(categories != null)return makeTopLinks(categories);
            }
            catch(Exception e)
            {
                logger.error(e);    
            }
            finally
            {
                HibernateSessionFactory.closeSession();
            }
        }
        catch(Exception e)
        {
            logger.warn(e);
        }
        return "";
    }
    /**
     * invoked by the above method makeTop
     * @param questionCategories
     * @return
     */
    private String makeTopLinks(Collection<QuestionCategory> questionCategories)
    {
        StringBuffer bf = new StringBuffer();
        HttpServletRequest request = (HttpServletRequest)this.pageContext.getRequest();
        if(questionCategories.size() > 0)
        {
            UserSession us = UserSessionUtil.getUserSession(request);
            boolean userHasAdminRight = false;
            if(us != null)
            {
                if("1".equals(us.getType()) || us.getIsSuper())
                {
                    userHasAdminRight = true;
                }
            }
            Iterator levelIte = questionCategories.iterator();
            QuestionCategory qc = null;
            String catType = "";
            String catState = "";
            while(levelIte.hasNext())
            {
                qc = (QuestionCategory)levelIte.next();
                catState = qc.getState();
                catType = qc.getOnlyForAdmin();
                //category is hide, only visible for admin
                if("1".equals(catState))
                {
                   continue;
                }
                else if("I".equals(catType))
                {
                    if(!userHasAdminRight)
                    {
                        continue;
                    }
                }
                else if("T".equals(catType))
                {
                    continue;
                }
                else if("Y".equals(catType))
                {
                    continue;
                }
                bf.append("<li><a href='");
                bf.append(request.getContextPath());
                if(qc.getType() == 0){
                	bf.append("/question.mrqa?action=list&catId=");
                }else if(qc.getType() == 1){
                	bf.append("/life.mrqa?action=list&catId=");
                }else if(qc.getType() == 2){
                	bf.append("/tech.mrqa?action=list&catId=");
                }
                bf.append(qc.getId());
                bf.append("'>");
                bf.append(qc.getName());
                bf.append("</a>");
            }
        }
        if(bf.toString().length() >0)
            return "<ul id=\"questioncategoryontop\">\n"+bf.toString()+"</ul>\n";
        else return "";
        
    }
    
    
    public void setType(String type)
    {
        this.type = type;
    }
    
    public String getType()
    {
        return type;
    }

	public String getCategoryType() {
		return categoryType;
	}

	public void setCategoryType(String categoryType) {
		this.categoryType = categoryType;
		if(categoryType != null){
			this.intCatType = new Integer(categoryType);
		}else{
			this.intCatType = null;
		}
	}
    
    
    
    
    
}
